package com.cloud.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cloud.dao.ConvertTaskDao;
import com.cloud.entity.*;
import com.cloud.service.AlgorithmService;
import com.cloud.service.ConvertTaskService;
import com.cloud.type.AlgorithmType;
import com.cloud.util.CommonUtil;
import com.cloud.util.JsonUtil;
import com.cloud.util.constants.ErrorEnum;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.logging.Logger;

import static com.cloud.util.EntityUtil.*;
import static com.cloud.util.constants.Constants.*;

/**
 * @author: cansong
 * @description: 任务/任务文件
 * @date: 2020/11/2 10:18
 */
@Service
public class ConvertTaskServiceImpl implements ConvertTaskService {

	private static final Logger LOG = Logger.getLogger(ConvertTaskServiceImpl.class.getName());

	@Autowired
	private ConvertTaskDao convertTaskDao;

	@Autowired
	private AlgorithmService algorithmService;

	/**
	 * 转换任务列表
	 */
	@Override
	public ResultPageEntity listConvertTask(JSONObject jsonObject) {
		CommonUtil.fillPageParam(jsonObject);
		int count = convertTaskDao.countConvertTask(jsonObject);
		List<JSONObject> list = convertTaskDao.listConvertTask(jsonObject);
		for(JSONObject item : list) {
			formatConvertTaskJSONObject(item);
		}
		return CommonUtil.successResultPage(jsonObject, list, count);
	}

	/**
	 * 添加转换任务
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity addConvertTask(ConvertTaskEntity convertTaskEntity) {
		int exist = convertTaskDao.queryExistConvertTask(convertTaskEntity);
		if (exist > 0) {
			return CommonUtil.resultFromJSON(CommonUtil.errorJson(ErrorEnum.E_10010));
		}

		formatConvertTaskEntityForDB(convertTaskEntity);
		convertTaskEntity.setTaskStatus(TASK_STATUS_CREATE);
		convertTaskDao.addConvertTask(convertTaskEntity);
		List<ConvertTaskFileEntity> taskFiles = convertTaskEntity.getTaskFiles();
		for(ConvertTaskFileEntity taskFileEntity : taskFiles) {
			taskFileEntity.setTaskId(convertTaskEntity.getId());
			taskFileEntity.setSourceFlag(SOURCE_FLAG_RAW);
			convertTaskDao.addConvertTaskFile(taskFileEntity);
		}
		formatConvertTaskEntity(convertTaskEntity);
		return CommonUtil.successResult(convertTaskEntity);
	}

	/**
	 * 更新转换任务
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity updateConvertTask(ConvertTaskEntity convertTaskEntity) {
		formatConvertTaskEntityForDB(convertTaskEntity);
		convertTaskDao.updateConvertTask(convertTaskEntity);
		formatConvertTaskEntity(convertTaskEntity);
		return CommonUtil.successResult(convertTaskEntity);
	}

	/**
	 *
	 * @param entity
	 * @return
	 * @description 删除转换任务
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity removeConvertTask(ConvertTaskEntity entity) {
		convertTaskDao.removeConvertTask(entity);
		return CommonUtil.successResult();
	}

	/**
	 * 增加转换任务文件
	 * @param convertTaskFileEntity
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity addConvertTaskFile(ConvertTaskFileEntity convertTaskFileEntity) {
		convertTaskDao.addConvertTaskFile(convertTaskFileEntity);
		return CommonUtil.successResult(convertTaskFileEntity);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity addConvertTaskFiles(List<ConvertTaskFileEntity> convertTaskFileEntityList) {
		for(ConvertTaskFileEntity entity : convertTaskFileEntityList) {
			convertTaskDao.addConvertTaskFile(entity);
		}
		return CommonUtil.successResult(convertTaskFileEntityList);
	}

	@Override
	public ResultEntity getConvertTaskByCondition(JSONObject condition) {
		JSONObject result = convertTaskDao.getConvertTaskByCodition(condition);
		formatConvertTaskJSONObject(result);
		return CommonUtil.successResult(result);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity newConvertTask(ConvertTaskEntity saveEntity) {
	    verifyEntity(saveEntity);
		ResultEntity newEntity = addConvertTask(saveEntity);
		if (newEntity.isSuccess()) {
			ResultEntity algorithmResult = algorithmService.callAlgorithm(saveEntity);
			LOG.warning("callAlgorithm Result: " + JsonUtil.toString(algorithmResult));
			// 算法服务状态更新
			ConvertTaskEntity updateEntity = updateFromAssignResult(saveEntity, algorithmResult);
			// 任务更新
			ResultEntity updateResult = updateConvertTask(updateEntity);
			LOG.warning("Update Result: " + JsonUtil.toString(updateEntity));

			if (algorithmResult.isSuccess()) { // 算法成功, 重新查询
				ConvertTaskEntity queryParam = new ConvertTaskEntity();
				queryParam.setId(updateEntity.getId());
				return getConvertTaskByCondition(queryParam);
			} else { // 返回更新结果
				ResultEntity failureAssign = new ResultEntity();
				failureAssign.putAll(updateEntity);
				failureAssign.setInfo(algorithmResult.getInfo());
				failureAssign.setCode(algorithmResult.getCode());
				failureAssign.setMsg(algorithmResult.getMsg());
				// 清理 algorithmInfo 转 Info
				// failureAssign.put("info", updateEntity.getAlgorithmInfo());
				failureAssign.remove("algorithmInfo");
				return failureAssign;
			}
		}
		return newEntity;
	}



	/**
	 * 根据转换文件获取任务
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity getConvertTaskByTaskFile(JSONObject condition) {
		List<JSONObject> tasks = convertTaskDao.getConvertTaskByTaskFile(condition);
		return CommonUtil.successResult(tasks);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity taskNotify(AlgorithmNotifyEntitiy notifyEntity) {
    	LOG.warning("notifyEntity:" + JsonUtil.toString(notifyEntity));
    	// 根据Notify创建Entity
		ConvertTaskEntity updateEntity = taskFromNotify(notifyEntity);
		// 任务更新
		ResultEntity updateResult = updateConvertTask(updateEntity);
		if (updateResult.isSuccess()) {
			// 保存转换文件
			List<ConvertTaskFileEntity> convertedFiles = notifyEntity.getConvertedFiles();
			for(ConvertTaskFileEntity fileEntity : convertedFiles) {
				fileEntity.setTaskId(notifyEntity.getId());
				fileEntity.setSourceFlag(SOURCE_FLAG_NOTIFY);
			}
			ResultEntity updateFileResult = addConvertTaskFiles(convertedFiles);
			if (updateFileResult.isSuccess()) {
				// 重新查询
				ConvertTaskEntity queryParam = new ConvertTaskEntity();
				queryParam.setId(updateEntity.getId());
				return getConvertTaskByCondition(queryParam);
			}
		}
		return updateResult;
	}


	/**
	 * 根据算法下发结果更新任务状态
	 * @param entity
	 * @param resultEntity
	 * @return
	 */
	private ConvertTaskEntity updateFromAssignResult(ConvertTaskEntity entity, ResultEntity resultEntity) {
		// 更新任务状态
		if (!SUCCESS_CODE.equals(resultEntity.getCode())) {
			entity.setTaskStatus(TASK_STATUS_ASSIGN_FAILURE);
		} else {
			entity.setTaskStatus(TASK_STATUS_ASSIGN_SUCCESS);
		}
		// 保存算法服务结果
		if (resultEntity.getInfo() != null) {
			entity.setAlgorithmInfo(resultEntity.getInfo());
		}
		return entity;
	}

	private ConvertTaskEntity taskFromNotify(AlgorithmNotifyEntitiy notifyEntity) {
		ConvertTaskEntity entity = new ConvertTaskEntity();
		entity.setId(notifyEntity.getId());
		entity.setTaskStatus(formatStatus(notifyEntity.getTaskStatus()));
		// 保存算法服务结果
		if (notifyEntity.getInfo() != null) {
			entity.setAlgorithmInfo(notifyEntity.getInfo());
		}
		return entity;
	}

	/**
	 *
	 * @param origStatus
	 * @return
	 */
	private String formatStatus(String origStatus) {
		return origStatus;
	}

	/**
	 * 
	 * @param entity
	 */
	private void verifyEntity(ConvertTaskEntity entity) {
        if (AlgorithmType.UNKNOWN.getType().equals(entity.getAlgorithmType())
                && !TASK_TYPE_VIDEO.equals(entity.getTaskType())) {
            throw new IllegalArgumentException("视频摘要算法只支持视频");
        }
    }
}
